//
// CrackBuild
//
// Copyright (C) jextra.net.
//
//  This file is part of the Crack build system.
//
//  The Crack build system is free software; you can redistribute it 
//  and/or modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  The Crack build system is distributed in the hope that it will be 
//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with the Crack build system; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//  02111-1307 USA.
//

package net.jextra.crack;

/**
 * <p>
 * All Build files MUST extend this class. This class includes the following features:
 * </p>
 * <ol>
 * <li>Manages {@link CrackCommand}s.
 * <li>Has a default "help" command that lists all registered commands.
 * <ol>
 */
public abstract class CrackBuild
{
    // ============================================================
    // Fields
    // ============================================================

    private static CrackBuild instance;

    private CrackCommander commander;

    // ============================================================
    // Constructors
    // ============================================================

    public CrackBuild()
    {
        setInstance( this );
        commander = new CrackCommander();
    }

    // ============================================================
    // Methods
    // ============================================================

    // ----------
    // public
    // ----------

    public static CrackBuild getInstance()
    {
        return instance;
    }

    @CrackCommand( description = "Display this help." )
    public void help()
        throws Exception
    {
        commander.printHelp( false );
    }

    @CrackCommand( description = "Display all commands even if they are 'hidden'.", visible = false )
    public void namespace()
        throws Exception
    {
        commander.printHelp( true );
    }

    public CrackContext getCrackContext()
    {
        return CrackContext.getInstance();
    }

    public void addCommands( Object commands )
        throws SecurityException, NoSuchMethodException
    {
        commander.addCommands( commands );
    }

    public void addCommands( String commandPrefix, Object commands )
        throws SecurityException, NoSuchMethodException
    {
        commander.addCommands( commandPrefix, commands );
    }

    public void createCommandAlias( String existingName, String aliasName )
    {
        commander.createCommandAlias( existingName, aliasName );
    }

    public void renameCommand( String oldName, String newName )
    {
        commander.renameCommand( oldName, newName );
    }

    public void setCommandVisible( String name, boolean visible )
    {
        commander.setCommandVisible( name, visible );
    }

    public boolean removeCommand( String name )
    {
        return commander.removeCommand( name );
    }

    public void invokeCommand( String command, String ... args )
        throws Exception
    {
        commander.invokeCommand( command, args );
    }

    public void invokeKnobCommand( Object knob, String command, String ... args )
        throws Exception
    {
        commander.invokeKnobCommand( knob, command, args );
    }

    public void clearCommandHistory()
    {
        commander.clearCommandHistory();
    }

    public void resetCommandLevel()
    {
        commander.resetCommandLevel();
    }

    public void printHeader( String message )
    {
        commander.printHeader( message );
    }

    // ----------
    // private
    // ----------

    private static void setInstance( CrackBuild newInstance )
    {
        assert instance == null : "Only one CrackBuild can be instantiated at one time";

        instance = newInstance;
    }
}
